﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace machine_tool
{
	public class MachineTool
	{
		public enum State
		{
			Complete = 0,
			IncX = 1,
			DecX = 2,
			IncY = 3,
			DecY = 4,
			IncZ = 5
		}

		private State _state;
		private State _state_ext;

		private int _x;
		private int _y;
		private int _z;

		private int _max_x;
		private int _max_y;
		private int _max_z;

		public MachineTool(int max_x, int max_y, int max_z)
		{
			_state = State.IncX;
			_state_ext = State.IncY;

			_x = 0;
			_y = 0;
			_z = 0;

			_max_x = max_x <= 0 ? 1 : max_x;
			_max_y = max_y <= 0 ? 1 : max_y;
			_max_z = max_z <= 0 ? 1 : max_z;
		}

		public int x { get { return _x; } }
		public int y { get { return _y; } }
		public int z { get { return _z; } }
		public State state { get { return _state; } }

		public void reset()
		{
			_state = State.IncX;
			_state_ext = State.IncY;

			_x = 0;
			_y = 0;
			_z = 0;
		}

		public State getNextState()
		{
			switch ( _state )
			{
				case State.IncZ:
				case State.IncY:
				case State.DecY:
				case State.IncX:
					if ( update(State.IncX) ) return _state = State.IncX;
					update(State.DecX);
					return _state = State.DecX;

				case State.DecX:
					if ( update(State.DecX) ) return State.DecX;
					if ( update(_state_ext) ) return _state = _state_ext;

					if ( !update(State.IncZ) ) break;
					_state_ext = _state_ext == State.DecY ? State.IncY : State.DecY;
					return _state = State.IncZ;
			}

			return _state = State.Complete;
		}

		private bool update( State act )
		{
			switch ( act )
			{
				case State.IncX:
					if ( _x + 1 >= _max_x ) return false;
					++_x;
					break;

				case State.DecX:
					if ( _x - 1 < 0 ) return false;
					--_x;
					break;

				case State.IncY:
					if ( _y + 1 >= _max_y ) return false;
					++_y;
					break;

				case State.DecY:
					if ( _y - 1 < 0 ) return false;
					--_y;
					break;

				case State.IncZ:
					if ( _z + 1 >= _max_z ) return false;
					++_z;
					break;
			}

			return true;
		}
	}
}
